import enum
from typing import Optional

from pydantic import BaseModel, Field


class TokenType(enum.Enum):
    TOKEN = 'token'
    REFRESH_TOKEN = 'refresh_token'
    PROJECT_TOKEN = 'project'


class Token(BaseModel):
    access_token: str = Field(default="", examples=["access_token"])
    refresh_token: str = Field(default="", examples=["refresh_token"])
    token_type: str = Field(default="bearer")


class PayloadDataUserInfo(BaseModel):
    id: int | None = None
    name: str | None = None
    username: str | None = None
    email: str | None = None
    avatar: str | None = None
    superuser: bool = False
    remember: bool = False
    type: str = "local"


class PayloadData(BaseModel):
    """
    iss：Issuer 发行人
    sub：Subject 主题
    exp：Expiration time到期时间
    aud：Audience 用户
    nbf：Not before 在此之前不可用
    iat：Issued at 发布时间
    jti：JWT ID用于标识该JWT
    scopes:
    data: 自定义字段
    """
    iss: str | None = None
    sub: str | None = None
    exp: int | str | None = None
    # 可以访问的网站资源
    aud: list[str] | str | None = None
    nbf: int | str | None = None
    iat: int | str | None = None
    jti: str | None = None
    scopes: list[str] = []
    # PayloadDataUserInfo 类型的 dict
    data: PayloadDataUserInfo | None = None


# 权限数据
class PermissionData(BaseModel):
    id: int = Field(default=0, examples=[0], description="权限ID")
    title: str = Field(default="", examples=[""], description="权限名称")
    url: str = Field(default="", examples=[""], description="权限路径")
    code: str = Field(default="", examples=[""], description="权限代码")
    method: str = Field(default="", examples=[""], description="请求方法，GET/POST/PUT/DELETE，其余的请求方法等使用到的时候再添加")


# 菜单数据
class MenuData(BaseModel):
    id: int = Field(default=0, examples=[0], description="菜单ID")
    title: str = Field(default="", examples=[""], description="菜单名称")
    icon: str = Field(default="", examples=[""], description="菜单图标，为空字符串时显示默认图标，为字符串None时不显示图标")
    parent: Optional[int] = Field(default=0, examples=[0], description="父级菜单ID")
    hidden: bool = Field(default=False, examples=[False], description="是否隐藏")
    permission_code: str = Field(default="", examples=[""], description="权限代码")
    link: str = Field(default="", examples=[""], description="链接，如果是外部链接则填写完整链接，如果是前端路由则填写路由路径")
    link_type: str = Field(default="", examples=[""], description="链接类型，可选值：routerLink, hrefLink")
    target: str = Field(default="", examples=[""], description="链接打开方式，可选值：_blank, _self，为空字符串时默认_self")
    level: int = Field(default=0, examples=[0], description="排序等级")
    status: str = Field(default="", examples=[""], description="状态")


# 用户访问权限数据
class UserAccessProfile(BaseModel):
    permissions: list[PermissionData] = Field(default=[], examples=[[]], description="用户权限数据")
    menus: list[MenuData] = Field(default=[], examples=[[]], description="用户菜单数据")
    superuser: bool = Field(default=False, examples=[False], description="是否是超级用户")


# 用户访问权限数据保存到缓存的数据结构
class UserAccessProfileCachePermissionData(BaseModel):
    GET: list[PermissionData] = Field(default=[], examples=[[]], description="GET请求权限数据")
    POST: list[PermissionData] = Field(default=[], examples=[[]], description="POST请求权限数据")
    PUT: list[PermissionData] = Field(default=[], examples=[[]], description="PUT请求权限数据")
    DELETE: list[PermissionData] = Field(default=[], examples=[[]], description="DELETE请求权限数据")


class UserAccessProfileCacheData(BaseModel):
    permissions: UserAccessProfileCachePermissionData = Field(default=UserAccessProfileCachePermissionData(), examples=[{}], description="用户权限数据")
    menus: list[MenuData] = Field(default=[], examples=[[]], description="用户菜单数据")
    superuser: bool = Field(default=False, examples=[False], description="是否是超级用户")


class JwtError(Exception):
    pass


class ScopeError(Exception):
    pass


class NoPermissionError(Exception):
    pass
